package com.yusysqdy.gulimail.order;

import org.springframework.amqp.rabbit.annotation.EnableRabbit;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;

/**
 * 使用rabbitmq
 *  1、引入amqp场景，RabbitAutoConfiguration就会自动生效
 *  2、给容器中自动配置了
 *      RabbitTemplate、AmqpAdmin、CachingConnectionFactory、RabbitMessagingTemplate
 *      所有的属性都是在 spring.rabbitmq
 *      @ConfigurationProperties(prefix="spring.rabbitmq")
 *  3、@EnableRabbit:想要监听消息必须具备的注解
 *  4、配置文件配置spring.rabbitmq信息
 *  5、监听消息：使用@RabbitListener:必须有@EnableRabbit
 *   @RabbitListener 类+方法上（监听哪些队列）
 *   @RabbitHandler 标在方法上（重载区分不同类型的消息）
 *
 *  6、RabbitMQ消息确认机制-可靠抵达，使用事务消息性能下降250倍比较明显，为此引入确认机制
 *      spring.rabbitmq.listener.simple.acknowledge-model=manual
 *      publisher confirmCallback确认机制
 *      publisher returnCallback未投递到queue退回模式
 *      consumer 消费端ack机制 ack用于肯定确认、nack用于否定确认批量，reject用户用于否定确认，不批量
 *
 *   7、feign远程调用丢失请求头的问题
 *      浏览器自带请求头自动发送带了cookie-> feign远程调用 ->请求没有任何请求头 ->没有请求头 远程服务认为没登录
 *      解决：加上feign远程调用拦截器
 *   8、feign异步情况会丢失上下文
 *      多线程情况下ThreadLocal的问题
 *      解决：RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); 开启多线程之前数据共享
 *
 *   9、幂等性解决方案
 *      令牌机制 token获取、比较、删除必须是原子性 所以使用lua脚本完成这个操作
 *      各种锁机制 数据库悲观锁、数据库乐观锁、业务层分布式锁
 *
 *   10、远程服务假失败、远程服务执行完成，下面的请求方法出现问题
 *       本地事务，在分布式系统，只能控制住自己的回滚，控制不了其他事务的回滚
 *       最大问题是网络抖动等原因无法判断是真失败还是假失败
 *
 *       本地事务：同一个方法内事务方法互调默认失效（一个类的一个方法内调用同类下其他方法，不管其他方法设置怎么样传播级别，都不会生效）
 *       原因：绕过了代理对象
 *       本地事务失效解决：
 *          1）引入aop-starter；spring-boot-starter-aop；引入aspectJ
 *          2）@EnableAspectJAutoProxy：开启AspectJ动态代理，以后所有代理均使用aspectJ创建（即使没有接口也可以代理接口）
 *              (exposeProxy = true) 对外暴露代理对象
 *          3）有本类方法调用才需要搞这些东西
 *    11、seata控制分布式事务
 *      1）每个微服务都要先安装undo_log
 *      2）安装并启动事务协调器：seata-server
 *        registry.conf 注册中心配置
 *      3）所有想要用到微服务分布式事务的微服务使用seata DataSourceProxy代理自己的数据源
 *      4）file.conf 修改vgroup_mapping.(应用名称)-fescar-service-group = "default"
 *      5）启动测试分布式事务
 *      6）给要使用分布式大事务的入口标注 @GlobalTranscational 开启全局事务
 *      7）每一个远程小事务使用 @Transcation 即可
 *      **整理使用十分简单 配置+服务启动+注解
 *      **使用消息队列解决 高并发情况下的分布式事务回滚消息通知（延迟队列）
 *    12、延迟队列 - 消息TTL+死信exchange -> 最终一致性
 *      使用场景1）下订单未支付锁库存30分钟自动关闭
 */

@EnableAspectJAutoProxy(exposeProxy = true)
@EnableRedisHttpSession
@EnableFeignClients
@EnableDiscoveryClient
@EnableRabbit
@SpringBootApplication
public class GulimailOrderApplication {

    public static void main(String[] args) {
        SpringApplication.run(GulimailOrderApplication.class, args);
    }

}
